/*
 * Finder.java
 *
 * Created on 24.jul.2007, 23:32:03
 *
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package glotton;

import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

/**
 *
 * @author tomase
 */
public class Finder implements Runnable {

    private List<String> searchSpace;
    private String characters;
    List<String> depot;
    List<String> results;
    final SearchListener owner;
    private String requiredPattern = "";
    private String requiredLetters = "";
    private boolean useRequiredPattern = false;
	private int wildcards;

    public Finder(SearchListener notify) {
    	owner = notify;
    	setSearchSpace(new LinkedList<String>());
    	setCharacters("");
    }

    public Finder(String charactersToUse, List<String> searchSpace, SearchListener notify) {
        this.setSearchSpace(searchSpace);
        setCharacters(charactersToUse);
        owner = notify;
    }

    public List<String> getSearchSpace() {
		return searchSpace;
	}

	public void setSearchSpace(List<String> searchSpace) {
		if (searchSpace != null){
			this.searchSpace = searchSpace;
		}
	}

	public String getCharacters() {
		return characters;
	}

	public void setCharacters(String characters) {
		this.characters = characters == null ? "" : characters.replaceAll("[*]", "");
		this.wildcards = 0;
		char[] array = characters.toCharArray();
		for (int i = 0; i < array.length; i++) {
			if (array[i] == '*'){
				this.wildcards++;
			}
		}
	}

	/**
     * Checks if the testWord given can be made using the characters in the
     * characters string.
     *
     * @param characters The characters to allow
     * @param testWord The word to check
     **/
    public boolean useable(String testWord) {
        String c = getCharacters();
        if (useRequiredPattern) {
        	c += requiredLetters;
        }
        
        if (testWord.length() == 0 || c.length() == 0 || testWord.length() > c.length() + wildcards) {
            return false;
        }

        int wildcardsUsed = 0;
        
        //iterate through
        for (int i = 0; i < testWord.length(); i++) {
        	if (testWord == "er"){
        		int a = 5;
        		a++;
        		System.out.println(a);
        	}
        	
        	if (useRequiredPattern && !matchesPattern(testWord)) {
        		return false;
        	}
        	
            int index = c.indexOf(testWord.charAt(i));

            if (index < 0) {
            	if (wildcardsUsed < this.wildcards) {
            		wildcardsUsed++;
            	}
            	else {
            		return false;
                }
            }
            else {
            	c = c.replaceFirst("" + testWord.charAt(i), "");
            }
        }

        return true;
    }

    private boolean matchesPattern(String testWord) {
		return Pattern.matches(requiredPattern, testWord);
	}


	public void run() {
        results = new LinkedList<String>();
        String startsWith = "a";
        int percentage = 0;
        for (String possible : getSearchSpace()) {
            if (possible.length() > 0) {
                if (!possible.startsWith(startsWith)) {
                    startsWith = "" + possible.charAt(0);
                    owner.progress(percentage);
                    percentage += 3;
                }
                if (useable(possible)) {
                    results.add(possible);
                }
            }
        }

        owner.done(results);
    }

	public String getRequiredPattern() {
		return requiredPattern;
	}


	public void setRequiredPattern(String pattern) {
		requiredPattern = pattern;
		extractLettersFromPattern();
		
		useRequiredPattern = (requiredPattern != null && requiredPattern != "");
	}


	private void extractLettersFromPattern() {
		requiredLetters = "";
		
		for(int i = 0; i < requiredPattern.length(); i++) {
			char c = requiredPattern.charAt(i);
			if (Character.isLetter(c)) {
				requiredLetters += c;
			}
		}
	}
}
